##
# AudienceStar module
# This file contains handlers for the basic features of AudienceStar,
# such as showing the index page and the main page for each Talk
##
import os

# Force Django to reload its settings.
#try:
#	from django.conf import settings
#	settings._target = None
#except:
#	pass
	# Must set this env var before importing any part of Django
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

	
# This defines all our data types that are stored in Google's database
from astarclasses import *
from google.appengine.api import urlfetch
from appengine_utilities import sessions
from google.appengine.api import channel
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from google.appengine.api import images
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
from google.appengine.api import mail
from datetime import datetime
from string import Template
import string
from string import *
import cgi
import logging
import sys
import random
import math
import re # regular expressions
import pickle
import time # to sleep
from dateutil.relativedelta import relativedelta
from hashlib import sha256 # for storing passwords as hashes
from random import random
from django.utils import simplejson as json

#random_key = random()
#sha256('%s%s%s'%('YOUR SECRET KEY',random_key,password))

from astarutils import * # this defines helpful functions like friendly date delta format

##
# Simply shows the index (about) page
class ViewIndex(BaseHandler):
	def get(self):
		user, admin_user = self.user_and_admin()
		if user:
			nickname = user.nickname()
		else:
			nickname = "guest"
		# get all the talks and compute avg ratings for each one
		all_talks = Talk.all()
		talks_stats = []
		for talk in all_talks:
			num_ratings = 0
			sum_ratings = 0
			topics = Topic.gql("WHERE ANCESTOR IS :1", talk)
			for topic in topics:
				num_ratings += topic.num_ratings
				sum_ratings += (topic.avg_rating * topic.num_ratings)
			if (num_ratings > 0):
				avg_rating = (sum_ratings/num_ratings)/4.0
				num_stars = int(round(avg_rating))
			else:
				num_stars = 0
				avg_rating = 0
			talk_data = {'title':talk.title, 'short_title':talk.short_title, 
						 'num_ratings': num_ratings, 'avg_rating':avg_rating,
						 'state':talk.state, 'num_stars':'stars'+str(num_stars),
						 'description':talk.description, 'icon_url':talk.icon_url}
			talks_stats.append(talk_data)
		self.render_template("index.html", {'user':user, 'nickname':nickname,
											'login_url':users.create_login_url('/'),
											'logout_url':users.create_logout_url("/"),
											'talks_stats':talks_stats})
			
class ViewFinal(BaseHandler):
	def get(self, talk_short_title):
		# find the talk identified by short title
		talk_query = Talk.gql("WHERE short_title = :1", lower(talk_short_title))
		talk = talk_query.get()
		if talk: # if we found a Talk matching short_title
			topics = Topic.gql("WHERE ANCESTOR IS :1", talk)
			comments = CommentQuestion.gql("WHERE ANCESTOR IS :1 ORDER BY created_date ASC", talk)
			params = {
				'talk': talk,
				'topics': topics,
				'comments': comments
			}
			self.render_template("finished.html", params)
		else:
			self.render_template("invalid_talk.html", {'short_title':talk_short_title})
			
			
class ViewTalk(BaseHandler):
	def get(self, talk_short_title):
		# find the talk identified by short title
		talk_query = Talk.gql("WHERE short_title = :1", lower(talk_short_title))
		talk = talk_query.get()
		if talk: # if we found a Talk matching short_title
			self.sess = sessions.Session() # get the unique session id to identify this client
			star = None # begin by assuming that no user (star) has been created for this session
			if self.sess.has_key("star_key"): # try to find a star associated with this session
				star = Star.get(self.sess["star_key"])
			if not star: # if no star was found, create a new one now
				star = Star(parent=talk, talk=talk)
				star.put()
				# give the datastore time to submit the commit
				time.sleep(1)
				self.sess["star_key"] = star.key()
			if not (self.sess.has_key('token')): # check to see if we have a channel already open, if not, create one
				self.sess['token'] = channel.create_channel(str(star.key().id()))
		
		if not talk: # If the short_title given doesn't match any valid Talks, show an error page
			self.render_template("invalid_talk.html", {'short_title':talk_short_title})
		elif talk.state in ("NOT_STARTED", "RANKING", "STARTED"):
			topics = Topic.gql("WHERE ANCESTOR IS :1", talk)
			rankings = TopicRanking.gql("WHERE ANCESTOR IS :1 AND star =:2", talk, star)
			# build a list of all topics that also includes this user's ranking for each topic (if they've ranked)
			topics_with_rankings = []
			for topic in topics:
				tr = {'key': topic.key(), 'title': topic.title, 'description': topic.description}
				for ranking in rankings:
					if ranking.topic.key() == topic.key():
						tr["ranking"] = ranking.value
				topics_with_rankings.append(tr)
			params = {
				'talk': talk,
				'topics': topics,
				'topics_with_rankings': topics_with_rankings,
				'token': self.sess['token'],
				'session_id': self.sess.sid,
				'star': star
			}
			self.render_template("talk_audience_page.html", params)
		elif talk.state == "FINISHED":
			self.redirect("/final/%s" % talk_short_title)
		

class GetTopics(BaseHandler):
	def get(self, talk_short_title):
		# find the talk identified by short title
		talk_query = Talk.gql("WHERE short_title = :1", lower(talk_short_title))
		talk = talk_query.get()
		if talk: # if we found a Talk matching short_title
			topics = Topic.gql("WHERE ANCESTOR IS :1 ORDER BY avg_ranking DESC", talk)
		else:
			topics=[{'title':'Invalid ID', 'description':'There is no talk with ID '+talk_short_title}]
		self.render_template("get_topics.html", {'topics':topics})
		

class GetRankings(BaseHandler):
	def get(self, talk_short_title):
		# find the talk identified by short title
		talk_query = Talk.gql("WHERE short_title = :1", lower(talk_short_title))
		talk = talk_query.get()
		if talk: # if we found a Talk matching short_title
			topics_query =  db.GqlQuery("SELECT * FROM Topic WHERE ANCESTOR IS :1 ORDER BY avg_ranking DESC", talk)
			topics_list = []
			sort_index = 1
			for topic in topics_query:
				topics_list.append({'key':str(topic.key()), 
				'data_id':'topic-'+str(topic.key().id()), 
				'num_very_interested':topic.num_very_interested, 
				'avg_ranking':round(50*topic.avg_ranking + 50, 1),
				'sort_index':sort_index})
				sort_index += 1
			message = {'success':'ok', 'message':'rankings_changed', 'topics_list':topics_list}
		else:
			message={'error':'No talk found with id:'+talk_short_title}
		self.response.out.write(json.dumps(message))
		
application = webapp.WSGIApplication([('/', ViewIndex),
					  ('/go/([a-zA-Z0-9]+)', ViewTalk),
					  ('/final/([a-zA-Z0-9)]+)', ViewFinal),
					  ('/get/topics/([a-zA-Z0-9]+)', GetTopics),
					  ('/get/rankings/([a-zA-Z0-9]+)', GetRankings),
					  ],
				     debug=True)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()
